package eng

import (
	"fmt"
	"golearnpro/pc/engs"
	"golearnpro/pc/net"
)

type Schedule interface {
	WorkerNotifier
	Submit(engs.Request)
	// 我有一个worker请问给我那个chan
	WorkerChan() chan engs.Request
	Run()
}

type WorkerNotifier interface {
	WorkerReady(chan engs.Request)
}

type Concurrent struct {
	Schedule    Schedule
	WorderCount int
	ItemChan    chan interface{}
}

func (e *Concurrent) Run(seeds ...engs.Request) {
	fmt.Println("in")

	// in := make(chan engs.Request)
	out := make(chan engs.ParseResult)

	// 内部调度器开始跑起来
	e.Schedule.Run()

	for _, item := range seeds {
		e.Schedule.Submit(item)
	}

	for i := 0; i < e.WorderCount; i++ {
		createWorker(e.Schedule.WorkerChan(), out, e.Schedule)
	}

	for {
		select {
		case m := <-out: // 它等着收 a
			// fmt.Println(m.Items)
			// 协程直接发给Item server
			for _, itm := range m.Items {
				go func() {
					e.ItemChan <- itm
				}()
			}
			for _, is := range m.Requests {
				e.Schedule.Submit(is) // 没收到就没法在写 b
			}
		}
	}
}

func createWorker(in chan engs.Request, out chan<- engs.ParseResult, s WorkerNotifier) {
	// 外边申请的worker每个都组成队列
	worker := in // 申请完了协程告诉里面已经完成了类似线程池的句柄申请句柄告诉里面可以消费了
	go func() {
		for {
			s.WorkerReady(worker)
			q := <-worker // 等着收 c  因为out 依赖 in in 又引来 out 所以循环等待 所以为了解耦 吧 in 给单独开协程写入
			html := net.Fether(q.Url)
			ps := q.ParserFunc(html)
			out <- ps
		}
	}()
}
